home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
mint104s.zoo
/
mint.src
/
dosmem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-08
|
34KB
|
1,287 lines
/*
Copyright 1990,1991,1992 Eric R. Smith.
Copyright 1992 Atari Corporation.
All rights reserved.
*/
/*
* GEMDOS emulation routines: these are for the GEMDOS system calls
* concerning allocating/freeing memory, including Pexec() (since
* this allocates memory) and Pterm() (since this, implicitly, frees
* it).
*/
#include "mint.h"
int procdate, proctime; /* set when any processes are created/destroyed */
static long do_vfork P_((int));
/*
* new call for TT TOS, for the user to inform DOS of alternate memory
* FIXME: we really shouldn't trust the user so completely
* FIXME: doesn't work if memory protection is on
*/
long ARGS_ON_STACK
m_addalt(start, size)
long start, size;
{
extern int no_mem_prot; /* see main.c and memprot.c */
if (!no_mem_prot) return 0; /* pretend to succeed */
if (!add_region(alt, start, size, M_ALT))
return EINTRN;
else
return 0;
}
/*
* internal routine for doing Malloc on a particular memory map
*/
long
_do_malloc(map, size, mode)
MMAP map;
long size;
int mode;
{
virtaddr v;
MEMREGION *m;
long maxsize, mleft;
if (size == -1L) {
maxsize = max_rsize(map);
if (curproc->maxmem) {
mleft = curproc->maxmem - memused(curproc);
if (maxsize > mleft)
maxsize = mleft;
if (maxsize < 0)
maxsize = 0;
}
/* make sure to round down */
return maxsize & ~MASKBITS;
}
/* special case: Malloc(0) should always return 0 */
if (size == 0)
return 0;
if (curproc->maxmem) { /* memory limit? */
if (size > curproc->maxmem - memused(curproc)) {
DEBUG(("malloc: memory request would exceed limit"));
return 0;
}
}
m = get_region(map, size, mode);
if (!m) {
return 0;
}
v = attach_region(curproc, m);
if (!v) {
m->links = 0;
free_region(m);
return 0;
}
/* NOTE: get_region returns a region with link count 1; since attach_region
* increments the link count, we have to remember to decrement the count
* to correct for this.
*/
m->links--;
if ((mode & F_KEEP)) { /* request for permanent memory */
m->mflags |= M_KEEP;
}
return (long)v;
}
long ARGS_ON_STACK
m_xalloc(size, mode)
long size;
int mode;
{
long r, r1;
int protmode;
#ifndef NO_DEBUG_INFO
int origmode = mode;
#endif
TRACE(("Mxalloc(%ld,%x)",size,mode));
/*
* AKP: Hack here: if the calling process' PC is in ROM, then this is a
* Malloc call made by VDI's v_opnvwk routine. So we change mode to
* include "super accessible." This is temporary, until VDI catches up
* with multitasking TOS.
*/
if (((mode & F_PROTMODE) == 0) &&
(curproc->ctxt[SYSCALL].pc > 0x00e00000L) &&
(curproc->ctxt[SYSCALL].pc < 0x00efffffL)) {
mode |= (F_PROT_S + 0x10) | F_KEEP;
TRACE(("m_xalloc: VDI special (call from ROM)"));
}
/*
* If the mode argument comes in a zero, then set it to the default
* value from prgflags. Otherwise subtract one from it to bring it
* into line with the actual argument to alloc_region.
*/
protmode = (mode & F_PROTMODE) >> F_PROTSHIFT;
if (protmode == 0) {
protmode = (curproc->memflags & F_PROTMODE) >> F_PROTSHIFT;
}
else --protmode;
#if 0
/* I'm very suspicious of the 0x08 flag; I can't see how it could
* work as the comment below seems to indicate -- ERS
*/
/*
* if the mode argument has the 0x08 bit set then you're trying to change
* the protection mode of a block you already own. "size" is really its
* base address. (new as of 2/6/92)
*/
if (mode & 0x08) change_prot_status(curproc,size,protmode);
#endif
/*
* Copy the F_KEEP attribute into protmode. We didn't do that
* before now because change_prot_status don't want to see no
* steenking nofree attributes.
*/
protmode |= (mode & F_KEEP);
/* mask off all but the ST/alternative RAM bits before further use */
mode &= 3;
if (mode == 0) {
r = _do_malloc(core, size, protmode);
goto ret;
}
else if (mode == 1) {
r = _do_malloc(alt, size, protmode);
goto ret;
}
else if (size == -1) {
/* modes 2 and 3 are the same for for size -1 */
r = _do_malloc(core, -1L, PROT_P);
r1 = _do_malloc(alt, -1L, PROT_P);
if (r1 > r) r = r1;
goto ret;
}
else if (mode == 2) {
r = _do_malloc(core, size, protmode);
if (r == 0) r = _do_malloc(alt, size, protmode);
goto ret;
}
else /* if (mode == 3) */ {
r = _do_malloc(alt, size, protmode);
if (r == 0) r = _do_malloc(core, size, protmode);
goto ret;
}
ret:
if (r == 0) {
DEBUG(("m_xalloc(%lx,%x) returns 0",size,origmode));
} else {
TRACE(("m_xalloc(%lx,%x) returns %lx",size,origmode,r));
}
return r;
}
long ARGS_ON_STACK
m_alloc(size)
long size;
{
long r;
TRACE(("Malloc(%lx)", size));
if (curproc->memflags & F_ALTALLOC)
r = m_xalloc(size, 3);
else
r = m_xalloc(size, 0);
TRACE(("Malloc: returning %lx", r));
return r;
}
long ARGS_ON_STACK
m_free(block)
virtaddr block;
{
MEMREGION *m;
int i;
TRACE(("Mfree(%lx)", block));
if (!block) {
DEBUG(("Mfree: null pointer"));
return EIMBA;
}
/* search backwards so that most recently allocated incarnations of
shared memory blocks are freed first (this doesn't matter very often)
*/
for (i = curproc->num_reg - 1; i >= 0; i--) {
if (curproc->addr[i] == block) {
m = curproc->mem[i];
assert(m != NULL);
assert(m->loc == (long)block);
curproc->mem[i] = 0;
curproc->addr[i] = 0;
m->links--;
if (m->links == 0) {
free_region(m);
}
return 0;
}
}
/* hmmm... if we didn't find the region, perhaps it's a global
* one (with the M_KEEP flag set) belonging to a process that
* terminated
*/
for (i = rootproc->num_reg - 1; i >= 0; i--) {
if (rootproc->addr[i] == block) {
m = rootproc->mem[i];
assert(m != NULL);
assert(m->loc == (long)block);
if (!(m->mflags & M_KEEP))
continue;
TRACE(("Freeing M_KEPT memory"));
rootproc->mem[i] = 0;
rootproc->addr[i] = 0;
m->links--;
if (m->links == 0) {
free_region(m);
}
return 0;
}
}
DEBUG(("Mfree: bad address %lx", block));
return EIMBA;
}
long ARGS_ON_STACK
m_shrink(dummy, block, size)
int dummy;
virtaddr block;
long size;
{
MEMREGION *m;
int i;
UNUSED(dummy);
TRACE(("Mshrink: %lx to %ld", block, size));
if (!block) {
DEBUG(("Mshrink: null pointer"));
return EIMBA;
}
for (i = 0; i < curproc->num_reg; i++) {
if (curproc->addr[i] == block) {
m = curproc->mem[i];
assert(m != NULL);
assert(m->loc == (long)block);
return shrink_region(m, size);
}
}
DEBUG(("Mshrink: bad address (%lx)", block));
return EIMBA;
}
long ARGS_ON_STACK
p_exec(mode, ptr1, ptr2, ptr3)
int mode;
void *ptr1, *ptr2, *ptr3;
{
MEMREGION *base,
*env = 0; /* assignment suppresses spurious warning */
MEMREGION *text = 0; /* for shared text regions */
PROC *p;
long r, flags = 0;
int i;
char mkbase = 0, mkload = 0, mkgo = 0, mkwait = 0, mkfree = 0;
char overlay = 0;
char thread = 0;
char ptrace;
char mkname = 0, *newname, *lastslash;
char localname[PNAMSIZ+1];
XATTR xattr;
int newpid;
/* tfmt and tail_offs are used for debugging only */
const char *tfmt = "Pexec(%d,%s,\"%s\",%lx)";
int tail_offs = 1;
/* the high bit of mode controls process tracing */
switch(mode & 0x7fff) {
case 0:
mkwait = 1; /* fall through */
case 100:
mkload = mkgo = mkfree = 1;
mkname = 1;
break;
case 200: /* overlay current process */
mkload = mkgo = 1;
overlay = mkname = 1;
break;
case 3:
mkload = 1;
break;
case 6:
mkfree = 1;
/* fall through */
case 4:
mkwait = mkgo = 1;
tfmt = "Pexec(%d,%lx,BP:%lx,%lx)";
tail_offs = 0;
break;
case 106:
mkfree = 1; /* fall through */
case 104:
thread = (mode == 104);
mkgo = 1;
mkname = (ptr1 != 0);
tfmt = "Pexec(%d,%s,BP:%lx,%lx)";
tail_offs = 0;
break;
case 206:
#if 0
/* mkfree has no effect when overlay is set, since
* in this case the "parent" and "child" are the same
* process; since the "child" will ru